<template>
  <a-modal
    v-model:visible="visible"
    :title="title"
    :mask-closable="false"
    :esc-to-close="false"
    :body-style="{ maxHeight: width >= 650 ? '76vh' : '100vh' }"
    :width="width >= 650 ? 650 : '100%'"
    @before-ok="save"
    @close="reset"
  >
    <a-form ref="formRef" :model="form" :rules="rules" size="large" auto-label-width :layout="width >= 700 ? 'horizontal' : 'vertical'">
      <fieldset>
        <legend>基础配置</legend>
        <a-row>
          <a-form-item label="任务名称" field="title">
            <a-input v-model.trim="form.title" placeholder="请输入任务名称" :max-length="64" show-word-limit />
          </a-form-item>
        </a-row>
        <a-form-item label="描述" field="description">
          <a-textarea
            v-model.trim="form.description"
            placeholder="请输入描述"
            show-word-limit
            :max-length="200"
            :auto-size="{ minRows: 3, maxRows: 5 }"
          />
        </a-form-item>
      </fieldset>
      <fieldset>
        <legend>调度配置</legend>
        <a-row>
          <a-col v-bind="colProps">
            <a-form-item label="触发类型" field="triggerType">
              <a-select
                v-model="form.triggerType"
                placeholder="请选择触发类型"
                :options="job_trigger_type_enum"
                @change="triggerTypeChange"
              />
            </a-form-item>
          </a-col>
          <a-col v-bind="colProps">
            <a-form-item
              v-if="form.triggerType === 1"
              label="间隔时长（秒）"
              field="fixedInterval"
              :rules="[{ required: true, message: '请输入间隔时长' }]"
            >
              <a-input-number
                v-model="form.fixedInterval"
                placeholder="请输入间隔时长"
              >
              </a-input-number>
            </a-form-item>
            <a-form-item
              v-else
              label="Cron表达式"
              field="cron"
              :rules="[{ required: true, message: '请输入Cron表达式' }]"
            >
              <div style="display: flex;">
                <a-auto-complete
                  v-model="form.cron"
                  :data="cron_list"
                  placeholder="请输入Cron表达式"
                  allow-clear
                >
                  <template #append>
                    <a-tooltip content="Cron表达式生成">
                      <a-button @click="openGeneratorCron(form.cron)">
                        <template #icon>
                          <icon-clock-circle />
                        </template>
                      </a-button>
                    </a-tooltip>
                  </template>
                </a-auto-complete>
              </div>
            </a-form-item>
          </a-col>
        </a-row>
      </fieldset>
      <fieldset>
        <legend>任务配置</legend>
        <a-row>
          <a-form-item label="任务类名" field="jobClassName">
            <a-select v-model="form.jobClassName" placeholder="请选择执行器" :options="jobClassList" allow-clear />
          </a-form-item>
        </a-row>
        <a-form-item label="任务参数" field="paramStr">
          <a-textarea
            v-model="form.paramStr"
            placeholder="请输入任务参数"
            :auto-size="{ minRows: 3, maxRows: 15 }"
          />
        </a-form-item>
      </fieldset>
    </a-form>

    <CronModal ref="CronModalRef" @ok="(e) => form.cron = e" />
  </a-modal>
</template>

<script setup lang="ts">
import { type ColProps, type FormInstance, Message } from '@arco-design/web-vue'
import { useWindowSize } from '@vueuse/core'
import { addJob, listJobClass, updateJob } from '@/apis/scheduler/job'
import { useResetReactive } from '@/hooks'
import { useDict } from '@/hooks/app'
import { isJson } from '@/utils/validate'
import CronModal from '@/components/GenCron/CronModel/index.vue'

const emit = defineEmits<{
  (e: 'save-success'): void
}>()

const { width } = useWindowSize()

const colProps: ColProps = { xs: 24, sm: 24, md: 12, lg: 12, xl: 12, xxl: 12 }

// 内置 Cron 表达式
const cron_list = [
  {
    label: '每分钟',
    value: '0 * * * * ?'
  },
  {
    label: '每30分钟',
    value: '0 0/30 * * * ?'
  },
  {
    label: '每小时',
    value: '0 0 * * * ?'
  },
  {
    label: '每天零点',
    value: '0 0 0 * * ?'
  },
  {
    label: '每月1日零点',
    value: '0 0 0 1 * ?'
  },
  {
    label: '每月最后一天零点',
    value: '0 0 0 L * ?'
  },
  {
    label: '每月最后一个工作日零点',
    value: '0 0 0 LW * ?'
  },
  {
    label: '每周日零点',
    value: '0 0 0 ? * 1'
  }
]

const dataId = ref()
const visible = ref(false)
const isUpdate = computed(() => !!dataId.value)
const title = computed(() => (isUpdate.value ? '修改任务' : '新增任务'))
const formRef = ref<FormInstance>()
const { job_trigger_type_enum } = useDict(
  'job_trigger_type_enum'
)

const rules: FormInstance['rules'] = {
  title: [{ required: true, message: '请输入任务名称' }],
  triggerType: [{ required: true, message: '请选择触发类型' }],
  jobClassName: [{ required: true, message: '请输入任务执行类名' }]
}

const [form, resetForm] = useResetReactive({
  title: '',
  description: '',
  triggerType: 1,
  fixedInterval: 60,
  cron: '',
  jobClassName: '',
  paramStr: ''
})

// 重置
const reset = () => {
  formRef.value?.resetFields()
  resetForm()
}

// 触发类型切换
const triggerTypeChange = () => {
  switch (form.triggerType) {
    case 1:
      form.fixedInterval = 60
      break
    case 2:
      form.cron = '0 * * * * ?'
      break
  }
}

const CronModalRef = ref<InstanceType<typeof CronModal>>()
// 打开生成表达式
const openGeneratorCron = (cron: string) => {
  CronModalRef.value?.open(cron)
}

// 保存
const save = async () => {
  try {
    const isInvalid = await formRef.value?.validate()
    const isValid = isJson(form.paramStr)
    if (!isValid) {
      Message.error('参数Param的JSON格式错误')
      return false
    }
    if (isInvalid) return false
    if (isUpdate.value) {
      await updateJob(dataId.value, form)
      Message.success('修改成功')
    } else {
      await addJob(form)
      Message.success('新增成功')
    }
    emit('save-success')
    return true
  } catch (error) {
    return false
  }
}

const jobClassList = ref()
// 获取classList
const fetchClassList = async () => {
  const { data } = await listJobClass()
  jobClassList.value = data?.map((item: string) => ({
    label: item,
    value: item
  }))
}

// 新增
const onAdd = async () => {
  reset()
  dataId.value = undefined
  visible.value = true
}

// 修改
const onUpdate = async (record: any) => {
  reset()
  dataId.value = record.id
  Object.assign(form, record)
  form.paramStr = JSON.stringify(record.param)
  visible.value = true
}

// 挂载
onMounted(async () => {
  await fetchClassList()
})

defineExpose({ onAdd, onUpdate })
</script>

<style scoped lang="scss">
fieldset {
  padding: 15px 15px 0 15px;
  margin-bottom: 15px;
  border: 1px solid var(--color-neutral-3);
  border-radius: 3px;
}
fieldset legend {
  color: rgb(var(--gray-10));
  padding: 2px 5px 2px 5px;
  border: 1px solid var(--color-neutral-3);
  border-radius: 3px;
}

.args-container {
  display: flex;
  flex-direction: column;
  width: 100%;
}

.args-item {
  display: flex;
  align-items: center;
  button {
    margin-bottom: 20px;
  }
}

.args-item > *:not(:last-child) {
  margin-right: 10px;
}

.add-button {
  align-self: flex-start;
  width: 100%;
}

:deep(.arco-input-append) {
  padding: 0;
  .arco-btn {
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
    border: 1px solid transparent;
  }
}
</style>
